package com.wz.jiangsu.main;

import cn.hutool.core.util.StrUtil;
import com.sun.management.OperatingSystemMXBean;
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;

import java.io.File;
import java.lang.management.ManagementFactory;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.text.DecimalFormat;
import java.util.Enumeration;
import java.util.concurrent.TimeUnit;

/**
 * @program: wz
 * @author: wangzhou
 * @create: 2023-12-19 17:10
 * @description:
 **/
public class GetComputerMessage {
    public static void main(String[] args) {
        getLocalHost();

        getWindowsIpAndMac();

        getCpuCount();

        getCpuInfo();

        getMemInfo();


    }

    public static void getLocalHost() {
        try {
            InetAddress ip = InetAddress.getLocalHost();
            String localName = ip.getHostName();
            String osName = System.getProperty("os.name");
            String userName = System.getProperty("user.name");
            String osVersion = System.getProperty("os.version");
            String osArch = System.getProperty("os.arch");

            System.out.println("当前用户：" + userName);
            System.out.println("用户的主目录：" + System.getProperty("user.home"));
            System.out.println("用户的当前工作目录：" + System.getProperty("user.dir"));
            System.out.println("主机名称：" + localName);
            System.out.println("主机系统：" + osName);
            System.out.println("系统版本：" + osVersion);
            System.out.println("系统架构：" + osArch);
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

    public static void getWindowsIpAndMac() {
        try {
            Enumeration<NetworkInterface> allNetInterfaces = NetworkInterface.getNetworkInterfaces();
            // 遍历网卡接口
            while (allNetInterfaces.hasMoreElements()) {
                NetworkInterface netInterface = allNetInterfaces.nextElement();
                // 去除回环接口，子接口，未运行和接口
                if (netInterface.isLoopback() || netInterface.isVirtual() || !netInterface.isUp()) {
                    continue;
                }

                // 重点来了：“经验”之谈
                // 为了过滤掉虚拟机的网卡，可以通过网卡名来进行基础过滤。windows主机ip对应的网卡名会包含下面三个：Intel  无线、Realtek  网线、Ethernet  兼容xp系统
                if (!netInterface.getDisplayName().contains("Intel")
                        && !netInterface.getDisplayName().contains("Realtek")
                        && !netInterface.getDisplayName().contains("Ethernet")) {
                    continue;
                }

                String ip = "";
                String mac = "";
                String niName = "";
                Enumeration<InetAddress> addresses = netInterface.getInetAddresses();
                while (addresses.hasMoreElements()) {
                    InetAddress ia = addresses.nextElement();
                    // 去除本地回环地址，子接口，未运行和地址
                    if (ia != null && !ia.isLoopbackAddress() && ia.isSiteLocalAddress() && !ia.isAnyLocalAddress()) {
                        // 判断是否是ip v4地址
                        if (ia instanceof Inet4Address) {
                            ip = ia.getHostAddress();
                            // 获取MAC地址
                            mac = getMac(ia);
                            niName = netInterface.getName();
                            if (StrUtil.isNotBlank(ip) && StrUtil.isNotBlank(mac) && StrUtil.isNotBlank(niName)) {
                                System.out.println("当前网卡：" + niName);
                                System.out.println("当前主机ip：" + ip);
                                System.out.println("当前主机MAC：" + mac);
                                return;
                            }
                        }
                    }
                }
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取MAC地址
     * @param ia
     * @return
     */
    public static String getMac(InetAddress ia){
        try {
            //获取网卡，获取地址
            byte[] mac = NetworkInterface.getByInetAddress(ia).getHardwareAddress();
            StringBuffer sb = new StringBuffer();
            if (mac != null && mac.length>0){
                for(int i=0; i<mac.length; i++) {
                    if(i!=0) {
                        sb.append("-");
                    }
                    //字节转换为整数
                    String str = Integer.toHexString(mac[i] & 0xff);
                    if(str.length()==1) {
                        sb.append("0").append(str);
                    }else {
                        sb.append(str);
                    }
                }
            }
            return sb.toString().toUpperCase();
        } catch (SocketException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取CPU核数
     */
    public static void getCpuCount(){
        try {
            // 获取SystemInfo实例
            SystemInfo systemInfo = new SystemInfo();
            // 获取CentralProcessor实例
            CentralProcessor processor = systemInfo.getHardware().getProcessor();
            // 获取CPU核数
            int cpuCount = processor.getLogicalProcessorCount();
            System.out.println("CPU核数："+cpuCount);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void getCpuInfo() {
        try {
            SystemInfo systemInfo = new SystemInfo();
            CentralProcessor processor = systemInfo.getHardware().getProcessor();
            // 获取系统范围的cpu负载技计数
            long[] prevTicks = processor.getSystemCpuLoadTicks();
            // 睡眠1s
            TimeUnit.SECONDS.sleep(1);
            long[] ticks = processor.getSystemCpuLoadTicks();
            // 具有良好优先级的用户级别
            long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()];
            // 硬件服务
            long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
            // 软服务使用
            long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
            // 管理程序使用
            long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
            // 系统使用
            long cSys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
            // 用户使用
            long user = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()];
            // 等待使用
            long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
            // 空闲使用
            long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
            long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal;
            double sysRate = cSys * 1.0 / totalCpu;
            double userRate = user * 1.0 / totalCpu;
            double waitRate = cSys * 1.0 / totalCpu;
            double idleRate = cSys * 1.0 / totalCpu;
            double betweenRate = processor.getSystemCpuLoadBetweenTicks();
            double cpuLoad = processor.getSystemCpuLoad();
            System.out.println("cpu系统使用率:" + new DecimalFormat("#.##%").format(sysRate));
            System.out.println("cpu用户使用率:" + new DecimalFormat("#.##%").format(userRate));
            System.out.println("cpu当前等待率:" + new DecimalFormat("#.##%").format(waitRate));
            System.out.println("cpu当前空闲率:" + new DecimalFormat("#.##%").format(idleRate));
            // 获取cpu最近(时间间隔内)使用率
            System.out.println("CPU load: "+ new DecimalFormat("#.##%").format(betweenRate) +"(counting ticks)");
            // 获取cpu使用率
            System.out.println("CPU load: "+ new DecimalFormat("#.##%").format(cpuLoad) +"(OS MXBean)");
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 获取主机内存
     */
    public static void getMemInfo(){
        try {
            OperatingSystemMXBean osmxb = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
            // 总内存，单位：字节
            long total = osmxb.getTotalPhysicalMemorySize();
            // 空闲内存，单位：字节
            long free = osmxb.getFreePhysicalMemorySize();
            // 可用内存，单位：字节
            long usable = osmxb.getFreePhysicalMemorySize();
            // 已使用内存，单位：字节
            long used = total - free;
            // 内存使用率
            double useRate = used * 1.0 / total;
            System.out.println("总共内存：" + new DecimalFormat("#.##").format(total*1.0 / Math.pow(1024,3)) + "G");
            System.out.println("空闲内存：" + new DecimalFormat("#.##").format(free*1.0 / Math.pow(1024,3)) + "G");
            System.out.println("已用内存：" + new DecimalFormat("#.##").format(used*1.0 / Math.pow(1024,3)) + "G");
            System.out.println("可用内存：" + new DecimalFormat("#.##").format(usable*1.0 / Math.pow(1024,3)) + "G");
            System.out.println("内存使用率：" + new DecimalFormat("#.##%").format(useRate * 100.0));
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * @param RADIX 内存进制大小，"经验"之谈是：Windows下进制是1024，Mac和Linux是1000
     */
    public static void getDiskInfo(int RADIX){
        // 统计总内存
        long total = 0;
        // 统计总空闲
        long free = 0;
        // 统计总可用
        long usable = 0;
        // 统计总已用
        long used = 0;
        // 磁盘总使用
        double usedRate = 0.0;
        try{
            File[] disks = File.listRoots();
            for (File file : disks){
                // 统计总量
                total += file.getTotalSpace();
                free += file.getFreeSpace();
                usable += file.getUsableSpace();
                used += file.getTotalSpace() - file.getFreeSpace();

                String diskPath = file.getPath();
                long diskTotal = file.getTotalSpace();
                long diskFree = file.getFreeSpace();
                long diskUsable = file.getUsableSpace();
                long diskUsed = diskTotal - diskFree;
                double diskUsedRate = diskUsed * 1.0 / diskTotal;

                System.out.println("磁盘路径：" + diskPath);
                System.out.println("总共空间："+ new DecimalFormat("#.##").format(diskTotal*1.0 / Math.pow(RADIX,3)) + "G");
                System.out.println("空闲空间："+ new DecimalFormat("#.##").format(diskFree*1.0 / Math.pow(RADIX,3)) + "G");
                System.out.println("可用空间："+ new DecimalFormat("#.##").format(diskUsable*1.0 / Math.pow(RADIX,3)) + "G");
                System.out.println("已用空间："+ new DecimalFormat("#.##").format(diskUsed*1.0 / Math.pow(RADIX,3)) + "G");
                System.out.println("空间使用率：" + new DecimalFormat("#.##%").format(diskUsedRate*100));

            }

            String rootPath = "/";
            usedRate = used * 1.0 / total;

            System.out.println("磁盘根路径："+ rootPath);
            System.out.println("主机总共空间："+ new DecimalFormat("#.##").format(total*1.0 / Math.pow(RADIX,3)) + "G");
            System.out.println("主机总空闲空间："+ new DecimalFormat("#.##").format(free*1.0 / Math.pow(RADIX,3)) + "G");
            System.out.println("主机总可用空间："+ new DecimalFormat("#.##").format(usable*1.0 / Math.pow(RADIX,3)) + "G");
            System.out.println("主机总已用空间："+ new DecimalFormat("#.##").format(used*1.0 / Math.pow(RADIX,3)) + "G");
            System.out.println("主机总使用率：" + new DecimalFormat("#.##%").format(usedRate*100.0));

        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
